#include<iostream>
#include<fstream>
#include<sstream>
#include<map>
#include<vector>
#include<cstring>
#include<stdlib.h>

using namespace std;



struct Tree{
    string KeyWord;
    vector<int>LineNum;
    Tree *left;
    Tree *right;
};

class BTree{
    public:
	BTree(){root=nullptr;}
	/*插入内容*/
	void insert(string _KeyWord,int _LineNum){
	    root=AddTree(root,_KeyWord,_LineNum);
	}
	~BTree(){
//	    FreeRoot();
	}

	void del(Tree *p){
	    if(p!=nullptr){
		del(p->left);
		del(p->right);
		delete p;
	    }
	    
	}

	void FreeRoot(){
	    if(root!=nullptr){
		del(root);
		root=nullptr;
	    }
//	    free( root);
	    //root->left=nullptr;
	    //root->right=nullptr;
	    //root=nullptr;
	    if(!LineText.empty()){
		LineText.erase(LineText.begin(),LineText.end());
	    }
	    if(!NewLineText.empty()){
		NewLineText.erase(NewLineText.begin(),NewLineText.end());
	    }
	}


	Tree* getRoot(){
//	    cout<<"getRoot"<<endl;
	    return root;
	}
	map<int,string>getLineText(){
	    return LineText;
	}
	map<int,vector<string>>getNewLineText(){
	    return NewLineText;
	}

	/*打印树*/
	void ShowRoot(){
	    lbr(root);
	    cout<<endl;
	}
	void ShowAllText(){
	    for(auto it=LineText.begin();it!=LineText.end();it++){
		cout<<it->first<<":"<<it->second<<endl;
	    }
	}
	void LineTextInsert(int _Line,string _LineText){
		LineText[_Line]=_LineText;
	}

	void NewLineTextInsert(int _Line,string _LineText){
	    NewLineText[_Line].push_back(_LineText);
	}

    private:
	Tree *AddTree(Tree *t,string _KeyWord,int _LineNum){
	    if(t==nullptr){
		auto p=new Tree;
		p->KeyWord=_KeyWord;
		p->LineNum.push_back(_LineNum);
		p->left=nullptr;
		p->right=nullptr;
		return p;
	    }
	    else if(t->KeyWord > _KeyWord){
		t->left=AddTree(t->left,_KeyWord,_LineNum);
	    }
	    else if(t->KeyWord < _KeyWord){
		t->right=AddTree(t->right,_KeyWord,_LineNum);
	    }
	    else{
		t->LineNum.push_back(_LineNum);
	    }
	    return t;
	}
	/*中序遍历 -左-根-右*/
	void lbr(Tree *p){
	    if(p!=nullptr){
		lbr(p->left);
		cout<<p->KeyWord<<" ";
		lbr(p->right);
	    }
	}

    private:
	Tree *root;
	map<int ,string>LineText;
	map<int ,vector<string>>NewLineText;
};




class TextClass{
    public:
	TextClass(string DestText):
	    DestText(DestText)
	 {
	     fstream openDestText(DestText,ios::in);
	     if(!openDestText.is_open())
	    throw string("error");
	     openDestText.close();
	     run();
	 }
	TextClass(){}
	~TextClass(){
	}

	void SetDestText(string DestText){//设定查询的文件
	    this->DestText=DestText;
	    
	    run();
	}

	BTree getBTree(){
	    return bt;
	}
	string translastword(string word,int inLineNum){//判断词尾是否有符号
	    int i=word.size()-1;
	    int inser=1;
	    string newword="";
	    string uword="";
	    uword+=word[i];
	    if((word[i]&0x80)==128){//判断是否多字节字符
		uword="";
		uword+=word[i-2];
		uword+=word[i-1];
		uword+=word[i];
		i=i-2;
		if((((uword[1]&0x84)>=132)&&((uword[1]&0xa9)<=169))){//判断是否中文符号
		    inser=0;
		}
	    }
	    if(inser==1){
		bt.insert(uword,inLineNum);
		newword="";
		for(int j=0;j<i;j++){
		    newword+=word[j];
		}
		word=newword;
		newword=uword;
	    }
	    i=word.size()-1;
	    if((inser==1)&&(!((word[i]>=65&&word[i]<=90)||((word[i]<=122)&&word[i]>=97)))){
		word=translastword(word,inLineNum);
	    }else{
		bt.NewLineTextInsert(inLineNum,word);
	    }
	    if(newword!="")
		bt.NewLineTextInsert(inLineNum,newword);
	    return word;
	}

	string transpreword(string word,int inLineNum){//处理首字符是符号
		string newword="";
		int i=word.size()-1;
		int j=1;
		int inser=1;
		string uword="";
		uword+=word[0];
		if((word[0]&0xc0)==192){//判断是否多字节
		    uword=word;
		    uword.resize(3);
		    if((((uword[1]&0x84)>=132)&&((uword[1]&0xa9)<=169))){//判断是否中文字符
			inser=0;
		    }
		    j=3;
		}
		if(inser==1){
		    bt.insert(uword,inLineNum);
		    bt.NewLineTextInsert(inLineNum,uword);
		    newword="";
		    for(;j<=i;j++){
			newword+=word[j];
		    }
		    word=newword;
		    newword="";
		}
		if((inser==1)&&(!((word[0]>=65&&word[0]<=90)||((word[0]<=122)&&word[0]>=97)))){
		    word=transpreword(word,inLineNum);
		}
		return word;
		}

	void run(){
	    bt.FreeRoot();//释放之前打开的文本
	    fstream inDestText(DestText,ios::in);
	    //fstream OutSave(SaveResult,ios::out);//保存分解后的DestText文本文件

	    string line,word;
	    int inLineNum=0;
	    while(getline(inDestText,line)){
		++inLineNum;
		bt.LineTextInsert(inLineNum,line);
		istringstream istream(line);
		//ostringstream ostream;//保存分解后的DestText文本文件
		while(istream>>word){
		    //修改成分开标点符号的部分，保存在bt的newLineText里
		    //判断首字符是否符号
		    if(!((word[0]>=65&&word[0]<=90)||((word[0]<=122)&&word[0]>=97))){
			word=transpreword(word,inLineNum);
		    }
		    int i=word.size()-1;
		    //判断尾字符是否符号
		    if(!((word[i]>=65&&word[i]<=90)||((word[i]<=122)&&word[i]>=97))){
			word=translastword(word,inLineNum);
		    }else{
			bt.NewLineTextInsert(inLineNum,word);
		    }
		    //----------------------------------------------

		    bt.insert(word,inLineNum);
		   // ostream<<word<<" "<<inLineNum<<" ";//保存分解DestText文本文件的内容
		}
		//OutSave<<ostream.str()<<endl;
	    }
	   // bt.ShowRoot();
	   // bt.ShowAllText();
	}

    private:
	string DestText;
	BTree  bt;

};

